﻿using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using System.Web.Routing;
using MvcContrib.Sorting;
using MvcContrib.UI.Grid;

namespace MvcContrib.Shp.UI.Themed.Grid
{
    /// <summary>
    /// HTML Table Grid Renderer that is themeable via jQuery UI themes and takes advantage of the MVCContrib Grid jQuery plugin
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class HtmlTableGridThemedRenderer<T> : HtmlTableGridRenderer<T> where T : class
    {
        #region Fields

        private const string DefaultCssClass = "grid";
        private bool _lightenUpGrid = true;

        #endregion Fields

        #region Ctors

        public HtmlTableGridThemedRenderer(ViewEngineCollection engines)
            : base(engines)
        {
        }

        public HtmlTableGridThemedRenderer()
        {
        }

        #endregion Ctors

        /// <summary>
        /// Reduce the markup sent to the client. The reduction is 50% on larger grids.
        /// The markup that is not rendered using this Renderer will be added on the client 
        /// via the jQuery plugin. The end result rendered on the client is the same.  Default is true.
        /// </summary>
        public HtmlTableGridThemedRenderer<T> LightenUp(bool lightenUp)
        {
            _lightenUpGrid = lightenUp;
            return this;
        }

        protected override void RenderHeaderCellStart(GridColumn<T> column)
        {
            if (_lightenUpGrid)
                base.RenderHeaderCellStart(column);
            else
            {
                var attributes = new Dictionary<string, object>(column.HeaderAttributes);

                if (!attributes.ContainsKey("class") || (attributes["class"] == null))
                {
                    attributes["class"] = "ui-state-default";
                }
                else
                {
                    attributes["class"] = attributes["class"] + " " + "ui-widget-default";
                }

                if (IsSortingEnabled && column.Sortable)
                {
                    var isSortedByThisColumn = (GridModel.SortOptions.Column == GenerateSortColumnName(column));

                    if (isSortedByThisColumn)
                    {
                        var sortClass = GridModel.SortOptions.Direction == SortDirection.Ascending
                                            ? "sort_asc"
                                            : "sort_desc";
                        sortClass = string.Join(" ", new[] {attributes["class"].ToString(), sortClass});
                        attributes["class"] = sortClass;
                    }
                }

                var attrs = BuildHtmlAttributes(attributes);
                if (attrs.Length > 0) attrs = " " + attrs;

                RenderText(string.Format("<th{0}>", attrs));
            }
        }

        protected override void RenderHeaderText(GridColumn<T> column)
        {
            if (IsSortingEnabled && column.Sortable)
            {
                var spanClass = "mc-grid-sort ui-icon ui-icon-carat-2-n-s";

                var sortColumnName = GenerateSortColumnName(column);

                var isSortedByThisColumn = GridModel.SortOptions.Column == sortColumnName;

                var sortOptions = new GridSortOptions
                                      {
                                          Column = sortColumnName
                                      };

                if (isSortedByThisColumn)
                {
                    sortOptions.Direction = (GridModel.SortOptions.Direction == SortDirection.Ascending)
                                                ? SortDirection.Descending
                                                : SortDirection.Ascending;

                    spanClass = string.Format("mc-grid-sort ui-icon {0}",
                                              (sortOptions.Direction == SortDirection.Ascending)
                                                  ? "ui-icon-triangle-1-n"
                                                  : "ui-icon-triangle-1-s");
                }
                else //default sort order
                {
                    sortOptions.Direction = GridModel.SortOptions.Direction;
                }

                var routeValues = CreateRouteValuesForSortOptions(sortOptions, GridModel.SortPrefix);

                //Re-add existing querystring)
                foreach (var key in
                    Context.RequestContext.HttpContext.Request.QueryString.AllKeys.Where(key => key != null).Where(key => !routeValues.ContainsKey(key)))
                {
                    routeValues[key] = Context.RequestContext.HttpContext.Request.QueryString[key];
                }

                var button = new TagBuilder("a");
                var span = new TagBuilder("span");
                span.AddCssClass(spanClass);

                button.InnerHtml = span.ToString(TagRenderMode.Normal) + column.DisplayName;

                var urlHelper = new UrlHelper(Context.RequestContext);
                var url = urlHelper.Action(null, routeValues);

                button.MergeAttribute("href", url);

                RenderText(button.ToString(TagRenderMode.Normal));
            }
            else
            {
                base.RenderHeaderText(column);
            }
        }

        private static RouteValueDictionary CreateRouteValuesForSortOptions(GridSortOptions sortOptions, string prefix)
        {
            if (string.IsNullOrEmpty(prefix))
            {
                return new RouteValueDictionary(sortOptions);
            }

            //There must be a nice way to do this...
            return new RouteValueDictionary(new Dictionary<string, object>
                                                {
                                                    {prefix + "." + "Column", sortOptions.Column},
                                                    {prefix + "." + "Direction", sortOptions.Direction}
                                                });
        }

        protected override void RenderStartCell(GridColumn<T> column, GridRowViewData<T> rowData)
        {
            var attributes = column.Attributes(rowData);

            if (!_lightenUpGrid)
            {
                if (!attributes.ContainsKey("class"))
                {
                    attributes["class"] = "ui-widget-content";
                }
                else
                {
                    attributes["class"] = attributes["class"] + " " + "ui-widget-content";
                }
            }

            var attrs = BuildHtmlAttributes(attributes);

            if (attrs.Length > 0)
            {
                attrs = " " + attrs;
            }

            RenderText(string.Format("<td{0}>", attrs));
        }

        protected override void RenderGridStart()
        {
            if (!GridModel.Attributes.ContainsKey("class"))
            {
                GridModel.Attributes["class"] = DefaultCssClass + " mc-grid-content ui-widget-content";
            }

            var attrs = BuildHtmlAttributes(GridModel.Attributes);

            if (attrs.Length > 0)
                attrs = " " + attrs;

            RenderText(string.Format("<table{0}>", attrs));
        }

        /// <summary>
        /// Renders the empty result set table row.
        /// </summary>
        protected override void RenderEmpty()
        {
            RenderHeadStart();
            RenderEmptyHeaderCellStart();
            RenderHeaderCellEnd();
            RenderHeadEnd();
            RenderBodyStart();
            RenderText("<tr class=\"empty-results\"><td><div class=\"ui-state-error\">" + GridModel.EmptyText +
                       "</div></td></tr>");
            RenderBodyEnd();
        }
    }
}